<!DOCTYPE html><html lang="en"><head>
<meta charset="UTF-8">
<meta name="generator" content="ReSpec 35.6.0">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
span.example-title{text-transform:none}
:is(aside,div).example,div.illegal-example{padding:.5em;margin:1em 0;position:relative;clear:both}
div.illegal-example{color:red}
div.illegal-example p{color:#000}
aside.example div.example{border-left-width:.1em;border-color:#999;background:#fff}
</style>
<style>
.issue-label{text-transform:initial}
.warning>p:first-child{margin-top:0}
.warning{padding:.5em;border-left-width:.5em;border-left-style:solid}
span.warning{padding:.1em .5em .15em}
.issue.closed span.issue-number{text-decoration:line-through}
.issue.closed span.issue-number::after{content:" (Closed)";font-size:smaller}
.warning{border-color:#f11;border-color:var(--warning-border,#f11);border-width:.2em;border-style:solid;background:#fbe9e9;background:var(--warning-bg,#fbe9e9);color:#000;color:var(--text,#000)}
.warning-title:before{content:"⚠";font-size:1.3em;float:left;padding-right:.3em;margin-top:-.3em}
li.task-list-item{list-style:none}
input.task-list-item-checkbox{margin:0 .35em .25em -1.6em;vertical-align:middle}
.issue a.respec-gh-label{padding:5px;margin:0 2px 0 2px;font-size:10px;text-transform:none;text-decoration:none;font-weight:700;border-radius:4px;position:relative;bottom:2px;border:none;display:inline-block}
</style>
<style>
dfn{cursor:pointer}
.dfn-panel{position:absolute;z-index:35;min-width:300px;max-width:500px;padding:.5em .75em;margin-top:.6em;font-family:"Helvetica Neue",sans-serif;font-size:small;background:#fff;background:var(--indextable-hover-bg,#fff);color:#000;color:var(--text,#000);box-shadow:0 1em 3em -.4em rgba(0,0,0,.3),0 0 1px 1px rgba(0,0,0,.05);box-shadow:0 1em 3em -.4em var(--tocsidebar-shadow,rgba(0,0,0,.3)),0 0 1px 1px var(--tocsidebar-shadow,rgba(0,0,0,.05));border-radius:2px}
.dfn-panel:not(.docked)>.caret{position:absolute;top:-9px}
.dfn-panel:not(.docked)>.caret::after,.dfn-panel:not(.docked)>.caret::before{content:"";position:absolute;border:10px solid transparent;border-top:0;border-bottom:10px solid #fff;border-bottom-color:var(--indextable-hover-bg,#fff);top:0}
.dfn-panel:not(.docked)>.caret::before{border-bottom:9px solid #a2a9b1;border-bottom-color:var(--indextable-hover-bg,#a2a9b1)}
.dfn-panel *{margin:0}
.dfn-panel b{display:block;color:#000;color:var(--text,#000);margin-top:.25em}
.dfn-panel ul a[href]{color:#333;color:var(--text,#333)}
.dfn-panel>div{display:flex}
.dfn-panel a.self-link{font-weight:700;margin-right:auto}
.dfn-panel .marker{padding:.1em;margin-left:.5em;border-radius:.2em;text-align:center;white-space:nowrap;font-size:90%;color:#040b1c}
.dfn-panel .marker.dfn-exported{background:#d1edfd;box-shadow:0 0 0 .125em #1ca5f940}
.dfn-panel .marker.idl-block{background:#8ccbf2;box-shadow:0 0 0 .125em #0670b161}
.dfn-panel a:not(:hover){text-decoration:none!important;border-bottom:none!important}
.dfn-panel a[href]:hover{border-bottom-width:1px}
.dfn-panel ul{padding:0}
.dfn-panel li{margin-left:1em}
.dfn-panel.docked{position:fixed;left:.5em;top:unset;bottom:2em;margin:0 auto;max-width:calc(100vw - .75em * 2 - .5em - .2em * 2);max-height:30vh;overflow:auto}
</style>
    
    
<meta name="color-scheme" content="light dark">
    
<title>Design Tokens Resolver Module 2025.10</title>
    
    
  
<style id="respec-mainstyle">
@keyframes pop{
0%{transform:scale(1,1)}
25%{transform:scale(1.25,1.25);opacity:.75}
100%{transform:scale(1,1)}
}
a.internalDFN{color:inherit;border-bottom:1px solid #99c;text-decoration:none}
a.externalDFN{color:inherit;border-bottom:1px dotted #ccc;text-decoration:none}
a.bibref{text-decoration:none}
.respec-offending-element:target{animation:pop .25s ease-in-out 0s 1}
.respec-offending-element,a[href].respec-offending-element{text-decoration:red wavy underline}
@supports not (text-decoration:red wavy underline){
.respec-offending-element:not(pre){display:inline-block}
.respec-offending-element{background:url() bottom repeat-x}
}
#references :target{background:#eaf3ff;animation:pop .4s ease-in-out 0s 1}
cite .bibref{font-style:italic}
a[href].orcid{padding-left:4px;padding-right:4px}
a[href].orcid>svg{margin-bottom:-2px}
ol.tof,ul.tof{list-style:none outside none}
.caption{margin-top:.5em;font-style:italic}
#issue-summary>ul{column-count:2}
#issue-summary li{list-style:none;display:inline-block}
details.respec-tests-details{margin-left:1em;display:inline-block;vertical-align:top}
details.respec-tests-details>*{padding-right:2em}
details.respec-tests-details[open]{z-index:999999;position:absolute;border:thin solid #cad3e2;border-radius:.3em;background-color:#fff;padding-bottom:.5em}
details.respec-tests-details[open]>summary{border-bottom:thin solid #cad3e2;padding-left:1em;margin-bottom:1em;line-height:2em}
details.respec-tests-details>ul{width:100%;margin-top:-.3em}
details.respec-tests-details>li{padding-left:1em}
.self-link:hover{opacity:1;text-decoration:none;background-color:transparent}
aside.example .marker>a.self-link{color:inherit}
.header-wrapper{display:flex;align-items:baseline}
:is(h2,h3,h4,h5,h6):not(#toc>h2,#abstract>h2,#sotd>h2,.head>h2){position:relative;left:-.5em}
:is(h2,h3,h4,h5,h6):not(#toch2)+a.self-link{color:inherit;order:-1;position:relative;left:-1.1em;font-size:1rem;opacity:.5}
:is(h2,h3,h4,h5,h6)+a.self-link::before{content:"§";text-decoration:none;color:var(--heading-text)}
:is(h2,h3)+a.self-link{top:-.2em}
:is(h4,h5,h6)+a.self-link::before{color:#000}
@media (max-width:767px){
dd{margin-left:0}
}
@media print{
.removeOnSave{display:none}
}
</style>
<meta name="description" content="This specification extends the format and
        describes a method to work with design tokens in
        multiple contexts (such as “light mode” and “dark mode” color themes).">
<link rel="canonical" href="https://www.designtokens.org/TR/2025.10/resolver/">
<style>
.hljs{--base:#fafafa;--mono-1:#383a42;--mono-2:#686b77;--mono-3:#717277;--hue-1:#0b76c5;--hue-2:#336ae3;--hue-3:#a626a4;--hue-4:#42803c;--hue-5:#ca4706;--hue-5-2:#c91243;--hue-6:#986801;--hue-6-2:#9a6a01}
@media (prefers-color-scheme:dark){
.hljs{--base:#282c34;--mono-1:#abb2bf;--mono-2:#818896;--mono-3:#5c6370;--hue-1:#56b6c2;--hue-2:#61aeee;--hue-3:#c678dd;--hue-4:#98c379;--hue-5:#e06c75;--hue-5-2:#be5046;--hue-6:#d19a66;--hue-6-2:#e6c07b}
}
.hljs{display:block;overflow-x:auto;padding:.5em;color:#383a42;color:var(--mono-1,#383a42);background:#fafafa;background:var(--base,#fafafa)}
.hljs-comment,.hljs-quote{color:#717277;color:var(--mono-3,#717277);font-style:italic}
.hljs-doctag,.hljs-formula,.hljs-keyword{color:#a626a4;color:var(--hue-3,#a626a4)}
.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#ca4706;color:var(--hue-5,#ca4706);font-weight:700}
.hljs-literal{color:#0b76c5;color:var(--hue-1,#0b76c5)}
.hljs-addition,.hljs-attribute,.hljs-meta-string,.hljs-regexp,.hljs-string{color:#42803c;color:var(--hue-4,#42803c)}
.hljs-built_in,.hljs-class .hljs-title{color:#9a6a01;color:var(--hue-6-2,#9a6a01)}
.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#986801;color:var(--hue-6,#986801)}
.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#336ae3;color:var(--hue-2,#336ae3)}
.hljs-emphasis{font-style:italic}
.hljs-strong{font-weight:700}
.hljs-link{text-decoration:underline}
</style>
<style>
var:hover{text-decoration:underline;cursor:pointer}
var.respec-hl{color:var(--color,#000);background-color:var(--bg-color);box-shadow:0 0 0 2px var(--bg-color)}
@media (prefers-color-scheme:dark){
var.respec-hl{filter:saturate(.9) brightness(.9)}
}
var.respec-hl-c1{--bg-color:#f4d200}
var.respec-hl-c2{--bg-color:#ff87a2}
var.respec-hl-c3{--bg-color:#96e885}
var.respec-hl-c4{--bg-color:#3eeed2}
var.respec-hl-c5{--bg-color:#eacfb6}
var.respec-hl-c6{--bg-color:#82ddff}
var.respec-hl-c7{--bg-color:#ffbcf2}
@media print{
var.respec-hl{background:0 0;color:#000;box-shadow:unset}
}
</style>
<style>
var{position:relative;cursor:pointer}
var[data-type]::after,var[data-type]::before{position:absolute;left:50%;top:-6px;opacity:0;transition:opacity .4s;pointer-events:none}
var[data-type]::before{content:"";transform:translateX(-50%);border-width:4px 6px 0 6px;border-style:solid;border-color:transparent;border-top-color:#222}
var[data-type]::after{content:attr(data-type);transform:translateX(-50%) translateY(-100%);background:#222;text-align:center;font-family:"Dank Mono","Fira Code",monospace;font-style:normal;padding:6px;border-radius:3px;color:#daca88;text-indent:0;font-weight:400}
var[data-type]:hover::after,var[data-type]:hover::before{opacity:1}
</style>
<script id="initialUserConfig" type="application/json">{
  "specStatus": "CG-FINAL",
  "group": "design-tokens",
  "thisVersion": "https://www.designtokens.org/TR/2025.10/resolver/",
  "latestVersion": "https://www.designtokens.org/TR/2025.10/resolver/",
  "prevVersion": null,
  "edDraftURI": null,
  "editors": [
    {
      "name": "Joren Broekema",
      "url": "https://code-workshop-kit.com/"
    },
    {
      "name": "Esther Cheran",
      "url": "https://github.com/esthercheran"
    },
    {
      "name": "Mike Kamminga",
      "url": "https://hyma.io"
    },
    {
      "name": "Andrew L’Homme"
    },
    {
      "name": "Drew Powers",
      "url": "https://pow.rs"
    },
    {
      "name": "Matthew Ström-Awn",
      "url": "https://matthewstrom.com"
    },
    {
      "name": "Lilith Wittmann",
      "url": "https://github.com/LilithWittmann"
    }
  ],
  "authors": [
    {
      "name": "Louis Chenais",
      "url": "https://bsky.app/profile/lucho.cool"
    },
    {
      "name": "James Nash",
      "url": "https://cirrus.twiddles.com"
    }
  ],
  "github": {
    "repoURL": "https://github.com/design-tokens/community-group",
    "branch": "main"
  },
  "tocIntroductory": true,
  "logos": [
    {
      "src": "/assets/dtcg-logo-on-color.svg",
      "url": "https://www.designtokens.org",
      "alt": "Design Tokens Community Group",
      "width": 128,
      "height": 128,
      "id": "dtcg-logo"
    }
  ],
  "publishISODate": "2025-10-28T00:00:00.000Z",
  "generatedSubtitle": "Final Community Group Report 28 October 2025"
}</script>
<link rel="stylesheet" href="https://www.w3.org/StyleSheets/TR/2021/cg-final">
<link rel="stylesheet" media="(prefers-color-scheme: dark)" href="https://www.w3.org/StyleSheets/TR/2021/dark.css"></head>
  <body class="h-entry"><div class="head">
    <p class="logos"><a class="logo" href="https://www.designtokens.org"><img crossorigin="" alt="Design Tokens Community Group" height="128" id="dtcg-logo" src="/assets/dtcg-logo-on-color.svg" width="128">
  </a></p>
    <h1 id="title" class="title">Design Tokens Resolver Module 2025.10</h1> 
    <p id="w3c-state">
      <a href="https://www.w3.org/standards/types#reports">Final Community Group Report</a>
      <time class="dt-published" datetime="2025-10-28">28 October 2025</time>
    </p>
    <dl>
      <dt>This version:</dt><dd>
              <a class="u-url" href="https://www.designtokens.org/TR/2025.10/resolver/">https://www.designtokens.org/TR/2025.10/resolver/</a>
            </dd>
      <dt>Latest published version:</dt><dd>
              <a href="https://www.designtokens.org/TR/2025.10/resolver/">https://www.designtokens.org/TR/2025.10/resolver/</a>
            </dd>
      
      
      
      
      
      <dt>Editors:</dt><dd class="editor p-author h-card vcard">
    <a class="u-url url p-name fn" href="https://code-workshop-kit.com/">Joren Broekema</a>
  </dd><dd class="editor p-author h-card vcard">
    <a class="u-url url p-name fn" href="https://github.com/esthercheran">Esther Cheran</a>
  </dd><dd class="editor p-author h-card vcard">
    <a class="u-url url p-name fn" href="https://hyma.io">Mike Kamminga</a>
  </dd><dd class="editor p-author h-card vcard">
    <span class="p-name fn">Andrew L’Homme</span>
  </dd><dd class="editor p-author h-card vcard">
    <a class="u-url url p-name fn" href="https://pow.rs">Drew Powers</a>
  </dd><dd class="editor p-author h-card vcard">
    <a class="u-url url p-name fn" href="https://matthewstrom.com">Matthew Ström-Awn</a>
  </dd><dd class="editor p-author h-card vcard">
    <a class="u-url url p-name fn" href="https://github.com/LilithWittmann">Lilith Wittmann</a>
  </dd>
      
      <dt>Authors:</dt><dd class="editor p-author h-card vcard">
    <a class="u-url url p-name fn" href="https://bsky.app/profile/lucho.cool">Louis Chenais</a>
  </dd><dd class="editor p-author h-card vcard">
    <a class="u-url url p-name fn" href="https://cirrus.twiddles.com">James Nash</a>
  </dd>
      <dt>Feedback:</dt><dd>
        <a href="https://github.com/design-tokens/community-group/">GitHub design-tokens/community-group</a>
        (<a href="https://github.com/design-tokens/community-group/pulls/">pull requests</a>,
        <a href="https://github.com/design-tokens/community-group/issues/new/choose">new issue</a>,
        <a href="https://github.com/design-tokens/community-group/issues/">open issues</a>)
      </dd>
      
    </dl>
    
    <p class="copyright">
          <a href="https://www.w3.org/policies/#copyright">Copyright</a>
          ©
          2025
          
          the Contributors to the Design Tokens Resolver Module 2025.10
          Specification, published by the
          <a href="https://www.w3.org/groups/cg/design-tokens">Design Tokens Community Group</a> under the
          <a href="https://www.w3.org/community/about/agreements/fsa/">W3C Community Final Specification Agreement (FSA)</a>. A human-readable
                <a href="https://www.w3.org/community/about/agreements/fsa-deed/">summary</a>
                is available.
              
        </p>
    <hr title="Separator for header">
  </div>
    <section id="abstract" class="introductory"><h2>Abstract</h2>
      <p>
        This specification extends the <a href="../format/">format</a> and
        describes a method to work with <a href="../">design tokens</a> in
        multiple contexts (such as “light mode” and “dark mode” color themes).
      </p>
    </section>

    <section id="sotd" class="introductory"><h2>Status of This Document</h2><p>
      This specification was published by the
      <a href="https://www.w3.org/groups/cg/design-tokens">Design Tokens Community Group</a>. It is not a W3C Standard nor is it
      on the W3C Standards Track.
      
            Please note that under the
            <a href="https://www.w3.org/community/about/agreements/final/">W3C Community Final Specification Agreement (FSA)</a>
            other conditions apply.
          
      Learn more about
      <a href="https://www.w3.org/community/">W3C Community and Business Groups</a>.
    </p>
      <p>
        This section describes the status of this document at the time of its
        publication. Other documents may supersede this document. A list of
        current W3C Community Group reports and the latest revision of this
        report can be found in the W3C Community Group reports index at
        <a href="https://www.w3.org/community/reports/">https://www.w3.org/community/reports/</a>.
      </p>
      <p>
        This document was published by the DTCG as a
        <a href="https://www.w3.org/policies/process/#RecsCR">Candidate Recommendation</a>
        following the definitions provided by the W3C process. Contributions to
        this draft are governed by
        <a href="https://www.w3.org/community/about/process/cla">
          Community Contributor License Agreement (CLA)</a>, as specified by the
        <a href="https://www.w3.org/community/about/process/#cgroups">W3C Community Group Process</a>.
      </p>
      <p>
        While not a W3C recommendation, this classification is intended to
        clarify that, after extensive consensus-building, this specification is
        intended for implementation.
      </p>
      <p>
        <strong>This specification is considered stable</strong>. Further
        updates will be provided in superseding specifications.
      </p>
    <p>
    <a href="https://github.com/design-tokens/community-group/issues/">GitHub Issues</a> are preferred for
          discussion of this specification.
        
    
  </p></section><nav id="toc"><h2 class="introductory" id="table-of-contents">Table of Contents</h2><ol class="toc"><li class="tocline"><a class="tocxref" href="#abstract">Abstract</a></li><li class="tocline"><a class="tocxref" href="#sotd">Status of This Document</a></li><li class="tocline"><a class="tocxref" href="#introduction"><bdi class="secno">1. </bdi>Introduction</a></li><li class="tocline"><a class="tocxref" href="#terminology"><bdi class="secno">2. </bdi>Terminology</a><ol class="toc"><li class="tocline"><a class="tocxref" href="#orthogonality"><bdi class="secno">2.1 </bdi>Orthogonality</a></li><li class="tocline"><a class="tocxref" href="#permutation"><bdi class="secno">2.2 </bdi>Permutation</a></li></ol></li><li class="tocline"><a class="tocxref" href="#filetype"><bdi class="secno">3. </bdi>Filetype</a><ol class="toc"><li class="tocline"><a class="tocxref" href="#format"><bdi class="secno">3.1 </bdi>Format</a></li><li class="tocline"><a class="tocxref" href="#file-extension"><bdi class="secno">3.2 </bdi>File extension</a></li><li class="tocline"><a class="tocxref" href="#mime-type"><bdi class="secno">3.3 </bdi>MIME type</a></li></ol></li><li class="tocline"><a class="tocxref" href="#syntax"><bdi class="secno">4. </bdi>Syntax</a><ol class="toc"><li class="tocline"><a class="tocxref" href="#root-level-properties"><bdi class="secno">4.1 </bdi>Root level properties</a><ol class="toc"><li class="tocline"><a class="tocxref" href="#name"><bdi class="secno">4.1.1 </bdi>Name</a></li><li class="tocline"><a class="tocxref" href="#version"><bdi class="secno">4.1.2 </bdi>Version</a></li><li class="tocline"><a class="tocxref" href="#description"><bdi class="secno">4.1.3 </bdi>Description</a></li><li class="tocline"><a class="tocxref" href="#sets"><bdi class="secno">4.1.4 </bdi>Sets</a></li><li class="tocline"><a class="tocxref" href="#modifiers"><bdi class="secno">4.1.5 </bdi>Modifiers</a><ol class="toc"><li class="tocline"><a class="tocxref" href="#contexts"><bdi class="secno">4.1.5.1 </bdi>Contexts</a></li><li class="tocline"><a class="tocxref" href="#description-0"><bdi class="secno">4.1.5.2 </bdi>Description</a></li><li class="tocline"><a class="tocxref" href="#default"><bdi class="secno">4.1.5.3 </bdi>Default</a></li><li class="tocline"><a class="tocxref" href="#resolution-count"><bdi class="secno">4.1.5.4 </bdi>Resolution count</a></li></ol></li><li class="tocline"><a class="tocxref" href="#resolution-order"><bdi class="secno">4.1.6 </bdi>Resolution Order</a><ol class="toc"><li class="tocline"><a class="tocxref" href="#inline-sets-and-modifiers"><bdi class="secno">4.1.6.1 </bdi>Inline sets and modifiers</a></li><li class="tocline"><a class="tocxref" href="#ordering-of-sets-and-modifiers"><bdi class="secno">4.1.6.2 </bdi>Ordering of sets and modifiers</a></li></ol></li></ol></li><li class="tocline"><a class="tocxref" href="#reference-objects"><bdi class="secno">4.2 </bdi>Reference objects</a><ol class="toc"><li class="tocline"><a class="tocxref" href="#invalid-pointers"><bdi class="secno">4.2.1 </bdi>Invalid pointers</a></li><li class="tocline"><a class="tocxref" href="#extending"><bdi class="secno">4.2.2 </bdi>Extending</a></li></ol></li><li class="tocline"><a class="tocxref" href="#extensions"><bdi class="secno">4.3 </bdi>$extensions</a></li><li class="tocline"><a class="tocxref" href="#defs"><bdi class="secno">4.4 </bdi>$defs</a></li></ol></li><li class="tocline"><a class="tocxref" href="#inputs"><bdi class="secno">5. </bdi>Inputs</a><ol class="toc"><li class="tocline"><a class="tocxref" href="#case-sensitivity"><bdi class="secno">5.1 </bdi>Case sensitivity</a></li><li class="tocline"><a class="tocxref" href="#enforcing-strings"><bdi class="secno">5.2 </bdi>Enforcing strings</a></li></ol></li><li class="tocline"><a class="tocxref" href="#resolution-logic"><bdi class="secno">6. </bdi>Resolution logic</a><ol class="toc"><li class="tocline"><a class="tocxref" href="#input-validation"><bdi class="secno">6.1 </bdi>Input validation</a></li><li class="tocline"><a class="tocxref" href="#ordering"><bdi class="secno">6.2 </bdi>Ordering</a></li><li class="tocline"><a class="tocxref" href="#aliases"><bdi class="secno">6.3 </bdi>Aliases</a></li><li class="tocline"><a class="tocxref" href="#resolution"><bdi class="secno">6.4 </bdi>Resolution</a></li></ol></li><li class="tocline"><a class="tocxref" href="#bundling"><bdi class="secno">7. </bdi>Bundling</a><ol class="toc"><li class="tocline"><a class="tocxref" href="#inlining-files"><bdi class="secno">7.1 </bdi>Inlining files</a></li><li class="tocline"><a class="tocxref" href="#using-defs-for-files"><bdi class="secno">7.2 </bdi>Using $defs for files</a></li></ol></li><li class="tocline"><a class="tocxref" href="#conformance"><bdi class="secno">8. </bdi>Conformance</a></li><li class="tocline"><a class="tocxref" href="#acknowledgements"><bdi class="secno">A. </bdi>Acknowledgments</a></li><li class="tocline"><a class="tocxref" href="#references"><bdi class="secno">B. </bdi>References</a><ol class="toc"><li class="tocline"><a class="tocxref" href="#normative-references"><bdi class="secno">B.1 </bdi>Normative references</a></li></ol></li></ol></nav>

    <section id="introduction" class="informative"><div class="header-wrapper"><h2 id="x1-introduction"><bdi class="secno">1. </bdi>Introduction</h2><a class="self-link" href="#introduction" aria-label="Permalink for Section 1."></a></div><p><em>This section is non-normative.</em></p>
<p>Consumers of design tokens often need to express alternate values that apply in different contexts. Such examples include, but are not limited to:</p>
<ul>
<li><strong>Theming</strong>, such as light mode, dark mode, and high contrast color modes</li>
<li><strong>Sizing</strong>, such as mobile (small), tablet (medium), desktop (large)</li>
<li><strong>Accessibility mode</strong>, such as reduced motion, colorblindness, etc.</li>
</ul>
<p>However, these alternate contexts are susceptible to <a href="https://en.wikipedia.org/wiki/Combinatorial_explosion">combinatorial explosion</a>, making storage and management unwieldy.</p>
<p>This format describes a mechanism for deduplicating all repeat values of tokens across all contexts as well as enumerating all permutations of contexts.</p>
</section>

    <section id="terminology"><div class="header-wrapper"><h2 id="x2-terminology"><bdi class="secno">2. </bdi>Terminology</h2><a class="self-link" href="#terminology" aria-label="Permalink for Section 2."></a></div>
<section class="informative" id="orthogonality"><div class="header-wrapper"><h3 id="x2-1-orthogonality"><bdi class="secno">2.1 </bdi>Orthogonality</h3><a class="self-link" href="#orthogonality" aria-label="Permalink for Section 2.1"></a></div><p><em>This section is non-normative.</em></p>


<p>A trait describing two or more contexts that each operate on exclusive tokens, i.e. do not overlap. Modifiers <em class="rfc2119">MAY</em> be orthogonal, but it are not required to be.</p>
<p>Making modifiers orthogonal as much as possible reduces cognitive load and reduces user error.</p>
<aside class="example" id="example-non-orthogonal-modifiers"><div class="marker">
    <a class="self-link" href="#example-non-orthogonal-modifiers">Example<bdi> 1</bdi></a><span class="example-title">: Non-orthogonal modifiers</span>
  </div>

<p>Given the following modifiers:</p>
<ol>
<li>A <strong>theme</strong> modifier has the values <strong>light</strong> and <strong>dark</strong>. Among its values, it provides a value for the <code>color.button</code> token.</li>
<li>A <strong>brand</strong> modifier has the values <strong>brandA</strong> and <strong>brandB</strong>. Among its values, it provides a value for the <code>color.button</code> token.</li>
</ol>
<p>Since both modifiers provide a value for the <code>color.button</code> token, this means array order determines the final value, i.e. <strong>non-orthogonal.</strong></p>
</aside>

</section>

<section id="permutation"><div class="header-wrapper"><h3 id="x2-2-permutation"><bdi class="secno">2.2 </bdi>Permutation</h3><a class="self-link" href="#permutation" aria-label="Permalink for Section 2.2"></a></div>
<p>A permutation is a single possible permutation of a resolver document. A permutation maps 1:1 to an <a href="#inputs">input</a>, but the term “input” emphasizes the <a href="#modifiers">modifier</a> contexts used, where “permutation” emphasizes the final set of tokens.</p>
</section></section>

    <section id="filetype"><div class="header-wrapper"><h2 id="x3-filetype"><bdi class="secno">3. </bdi>Filetype</h2><a class="self-link" href="#filetype" aria-label="Permalink for Section 3."></a></div>
<section id="format"><div class="header-wrapper"><h3 id="x3-1-format"><bdi class="secno">3.1 </bdi>Format</h3><a class="self-link" href="#format" aria-label="Permalink for Section 3.1"></a></div>
<p>A resolver document <em class="rfc2119">MUST</em> use standard JSON syntax ([<cite><a class="bibref" data-link-type="biblio" href="#bib-rfc8259" title="The JavaScript Object Notation (JSON) Data Interchange Format">RFC8259</a></cite>]).</p>
<p>Tools <em class="rfc2119">MAY</em> support extensions such as <a href="https://jsonc.org/">JSONC</a> or <a href="https://json5.org/">JSON5</a> so long as the document may be converted to normal JSON without affecting token values.</p>
</section><section id="file-extension"><div class="header-wrapper"><h3 id="x3-2-file-extension"><bdi class="secno">3.2 </bdi>File extension</h3><a class="self-link" href="#file-extension" aria-label="Permalink for Section 3.2"></a></div>
<p>Users <em class="rfc2119">SHOULD</em> use the <code>.resolver.json</code> file extension to name resolver documents.</p>
</section><section id="mime-type"><div class="header-wrapper"><h3 id="x3-3-mime-type"><bdi class="secno">3.3 </bdi>MIME type</h3><a class="self-link" href="#mime-type" aria-label="Permalink for Section 3.3"></a></div>
<p>When transmitting a resolver document over HTTP, users <em class="rfc2119">SHOULD</em> use the expected <code>application/json</code> MIME type ([<cite><a class="bibref" data-link-type="biblio" href="#bib-rfc6838" title="Media Type Specifications and Registration Procedures">RFC6838</a></cite>]) in the <code>Content-Type</code> header ([<cite><a class="bibref" data-link-type="biblio" href="#bib-rfc1341" title="MIME (Multipurpose Internet Mail Extensions): Mechanisms for Specifying and Describing the Format of Internet Message Bodies">RFC1341</a></cite>]). Users <em class="rfc2119">SHOULD NOT</em> use a custom or unexpected MIME type.</p>
</section></section>

    <section id="syntax"><div class="header-wrapper"><h2 id="x4-syntax"><bdi class="secno">4. </bdi>Syntax</h2><a class="self-link" href="#syntax" aria-label="Permalink for Section 4."></a></div>
<section id="root-level-properties"><div class="header-wrapper"><h3 id="x4-1-root-level-properties"><bdi class="secno">4.1 </bdi>Root level properties</h3><a class="self-link" href="#root-level-properties" aria-label="Permalink for Section 4.1"></a></div>
<p>A resolver document contains the following properties at the root level:</p>
<table>
<thead>
<tr>
<th align="left">Name</th>
<th align="left">Type</th>
<th align="center">Required</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><a href="#name"><strong>name</strong></a></td>
<td align="left"><code>string</code></td>
<td align="center"></td>
<td align="left">A short, human-readable name for the document.</td>
</tr>
<tr>
<td align="left"><a href="#version"><strong>version</strong></a></td>
<td align="left"><code>YYYY.MM</code></td>
<td align="center">Y</td>
<td align="left">Version. Must be <code>2025.10</code>.</td>
</tr>
<tr>
<td align="left"><a href="#description"><strong>description</strong></a></td>
<td align="left"><code>string</code></td>
<td align="center"></td>
<td align="left">A human-readable description for this document.</td>
</tr>
<tr>
<td align="left"><a href="#sets"><strong>sets</strong></a></td>
<td align="left">Map[<code>string</code>, Set]</td>
<td align="center"></td>
<td align="left">Definition of sets.</td>
</tr>
<tr>
<td align="left"><a href="#modifiers"><strong>modifiers</strong></a></td>
<td align="left">Map[`string, Modifier]</td>
<td align="center"></td>
<td align="left">Definition of modifiers.</td>
</tr>
<tr>
<td align="left"><a href="#resolution-order"><strong>resolutionOrder</strong></a></td>
<td align="left"><code>(ReferenceObject | Set | Modifier)[]</code></td>
<td align="center">Y</td>
<td align="left">Resolution of sets and modifiers.</td>
</tr>
</tbody></table>
<section id="name"><div class="header-wrapper"><h4 id="x4-1-1-name"><bdi class="secno">4.1.1 </bdi>Name</h4><a class="self-link" href="#name" aria-label="Permalink for Section 4.1.1"></a></div>
<p>The document <em class="rfc2119">MAY</em> provide a human-readable <code>name</code> at the root level. This is helpful to distinguish one resolver document from another, in case the filename itself isn’t enough.</p>
</section><section id="version"><div class="header-wrapper"><h4 id="x4-1-2-version"><bdi class="secno">4.1.2 </bdi>Version</h4><a class="self-link" href="#version" aria-label="Permalink for Section 4.1.2"></a></div>
<p>The document <em class="rfc2119">MUST</em> provide a version at the root level, and it <em class="rfc2119">MUST</em> be <code>2025.10</code>. This is reserved for future versions in case breaking changes are introduced.</p>
</section><section id="description"><div class="header-wrapper"><h4 id="x4-1-3-description"><bdi class="secno">4.1.3 </bdi>Description</h4><a class="self-link" href="#description" aria-label="Permalink for Section 4.1.3"></a></div>
<p>The document <em class="rfc2119">MAY</em> provide a <code>description</code> at the root level. This may be used to add additional explanation or context not present in <a href="#name">name</a>.</p>
</section><section id="sets"><div class="header-wrapper"><h4 id="x4-1-4-sets"><bdi class="secno">4.1.4 </bdi>Sets</h4><a class="self-link" href="#sets" aria-label="Permalink for Section 4.1.4"></a></div>
<p>A set is a collection of design tokens in <a href="../format/">DTCG format</a>. A set <em class="rfc2119">MUST</em> contain a <code>sources</code> array with tokens declared directly, or a <a href="#reference-objects">reference object</a> pointing to a JSON file containing design tokens, or any combination of the two.</p>
<p>A set <em class="rfc2119">MAY</em> include a <code>description</code> describing the purpose of the set.</p>
<p>If the array declares multiple sources, they will be merged in array order, meaning if a token is declared multiple times, the last occurrence in the array will be the final value. Tools <em class="rfc2119">MUST</em> respect array ordering.</p>
<aside class="example" id="example-sets-comprising-remote-files-and-inline-tokens"><div class="marker">
    <a class="self-link" href="#example-sets-comprising-remote-files-and-inline-tokens">Example<bdi> 2</bdi></a><span class="example-title">: Sets comprising remote files and inline tokens</span>
  </div>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"sets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"color"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"description"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Color tokens"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
        <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"base/legacy.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
        <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"base/foundation.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
        <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"base/color-ramps.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
        <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"base/semantic.json"</span> <span class="hljs-punctuation">}</span>
      <span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"size"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"description"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Dimension, margin, and spacing tokens"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
        <span class="hljs-punctuation">{</span>
          <span class="hljs-attr">"space"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
            <span class="hljs-attr">"base"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
              <span class="hljs-attr">"100"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
                <span class="hljs-attr">"$type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"dimension"</span><span class="hljs-punctuation">,</span>
                <span class="hljs-attr">"$value"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"value"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">2</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"unit"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"rem"</span> <span class="hljs-punctuation">}</span>
              <span class="hljs-punctuation">}</span>
            <span class="hljs-punctuation">}</span>
          <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">}</span>
      <span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">}</span>
</code></pre>
</aside>

</section><section id="modifiers"><div class="header-wrapper"><h4 id="x4-1-5-modifiers"><bdi class="secno">4.1.5 </bdi>Modifiers</h4><a class="self-link" href="#modifiers" aria-label="Permalink for Section 4.1.5"></a></div>
<p>A modifier is similar to a <a href="#sets">set</a>, but allows for conditional inclusion via the <a href="#contexts">contexts</a> map.</p>
<section id="contexts"><div class="header-wrapper"><h5 id="x4-1-5-1-contexts"><bdi class="secno">4.1.5.1 </bdi>Contexts</h5><a class="self-link" href="#contexts" aria-label="Permalink for Section 4.1.5.1"></a></div>
<p>A modifier <em class="rfc2119">MUST</em> declare a <code>contexts</code> map of a <code>string</code> value to an array of token sources. The array of tokens sources <em class="rfc2119">MUST</em> be a <a href="#reference-objects">ReferenceObject</a>, inline tokens, or any combination of the two.</p>
<p>A modifier <em class="rfc2119">SHOULD</em> have two or more <code>contexts</code>, since one is the equivalent of a <a href="#sets">set</a>. A modifier <em class="rfc2119">MUST NOT</em> have an empty <code>contexts</code> map. Tools <em class="rfc2119">SHOULD</em> throw an error for modifiers with only 1 context. Tools <em class="rfc2119">MUST</em> throw an error for modifiers with 0 contexts.</p>
<p>Like <a href="#sets">sets</a>, array order <em class="rfc2119">MUST</em> be respected such that in case of conflict, the last occurrence of a token in the array produces the final value.</p>
<p>A modifier <em class="rfc2119">MAY</em> reference a <a href="#sets">set</a> inside a context value. However a modifier <em class="rfc2119">MUST NOT</em> reference any other modifier, not even another context inside the same modifier.</p>
<aside class="example" id="example-color-theme-modifier"><div class="marker">
    <a class="self-link" href="#example-color-theme-modifier">Example<bdi> 3</bdi></a><span class="example-title">: Color theme modifier</span>
  </div>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"modifiers"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"description"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Color theme"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"contexts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"light"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/light.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"lightHighContrast"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/light.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark-high-contrast.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"dark"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"darkHighContrast"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark-high-contrast.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"default"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"light"</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">}</span>
</code></pre>
</aside>

<aside class="example" id="example-modifier-referencing-a-set"><div class="marker">
    <a class="self-link" href="#example-modifier-referencing-a-set">Example<bdi> 4</bdi></a><span class="example-title">: Modifier referencing a set</span>
  </div>

<p>A modifier <em class="rfc2119">MAY</em> reference a <a href="#sets">set</a> inside a context value. This is equivalent to the <code>sources</code> being inlined in the same array. For example, the following:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"sets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"baseSize"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"size/base.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"modifiers"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"size"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"description"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Application size"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"contexts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"small"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/baseSize"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"device/mobile.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"typography/mobile.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"medium"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/baseSize"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"device/tablet.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"typography/base.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"large"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/baseSize"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"device/desktop.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"typography/base.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>Is equivalent to:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"sets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"baseSize"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-comment">// …</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"modifiers"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"size"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"description"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Application size"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"contexts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"small"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"size/base.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"device/mobile.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"typography/mobile.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"medium"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"size/base.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"device/tablet.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"typography/base.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"large"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"size/base.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"device/desktop.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"typography/base.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">}</span>
</code></pre>
</aside>

</section><section id="description-0"><div class="header-wrapper"><h5 id="x4-1-5-2-description"><bdi class="secno">4.1.5.2 </bdi>Description</h5><a class="self-link" href="#description-0" aria-label="Permalink for Section 4.1.5.2"></a></div>
<p>A modifier <em class="rfc2119">MAY</em> declare a human-readable <code>description</code>.</p>
</section><section id="default"><div class="header-wrapper"><h5 id="x4-1-5-3-default"><bdi class="secno">4.1.5.3 </bdi>Default</h5><a class="self-link" href="#default" aria-label="Permalink for Section 4.1.5.3"></a></div>
<p>A modifier <em class="rfc2119">MAY</em> declare a <code>default</code> value that <em class="rfc2119">MUST</em> match one of the keys in <code>contexts</code>. Tools <em class="rfc2119">MUST</em> throw an error if the value is not present in <code>contexts</code>.</p>
</section><section id="resolution-count"><div class="header-wrapper"><h5 id="x4-1-5-4-resolution-count"><bdi class="secno">4.1.5.4 </bdi>Resolution count</h5><a class="self-link" href="#resolution-count" aria-label="Permalink for Section 4.1.5.4"></a></div>
<p>The number of possible <a data-link-type="dfn" href="https://www.w3.org/policies/process/#group-decision">resolutions</a> a document may generate may be predicted with the product of all <code>contexts</code> across all modifiers.</p>
<aside class="example" id="example-calculating-resolutions"><div class="marker">
    <a class="self-link" href="#example-calculating-resolutions">Example<bdi> 5</bdi></a><span class="example-title">: Calculating resolutions</span>
  </div>

<ul>
<li>If a document had 2 modifiers that each had 2 <code>contexts</code>, that resolver may produce 4 resolutions, or 2 × 2.</li>
<li>If a document had 3 modifiers with 4, 3, and 2 <code>contexts</code> respectively, that resolver may produce 24 resolutions, or 4 × 3 × 2.</li>
</ul>
</aside>

</section></section><section id="resolution-order"><div class="header-wrapper"><h4 id="x4-1-6-resolution-order"><bdi class="secno">4.1.6 </bdi>Resolution Order</h4><a class="self-link" href="#resolution-order" aria-label="Permalink for Section 4.1.6"></a></div>
<p>The <code>resolutionOrder</code> key is an array of <a href="#sets">sets</a> and <a href="#modifiers">modifiers</a> ordered to produce the final result of tokens. The order is significant, with tokens later in the array overriding any tokens that came before them, in case of conflict.</p>
<aside class="example" id="example-composing-sets-and-modifiers-together"><div class="marker">
    <a class="self-link" href="#example-composing-sets-and-modifiers-together">Example<bdi> 6</bdi></a><span class="example-title">: Composing sets and modifiers together</span>
  </div>

<p>Given a <code>resolutionOrder</code> that consists of multiple sets and modifiers:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"sets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"size"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"foundation/size.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"typography"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"foundation/typography.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"animation"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"foundation/animation.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"modifiers"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"description"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Color theme"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"contexts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"light"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/light.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"lightHighContrast"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/light.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark-high-contrast.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"dark"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"darkHighContrast"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark-high-contrast.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"default"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"light"</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"resolutionOrder"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/size"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/typography"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/animation"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/modifiers/theme"</span> <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>This merely describes multiple final results of tokens. We’ll need an <a href="#inputs">input</a> to produce the final sets.</p>
<p>Given the following inputs, we would get the following resolution order:</p>
<table><thead><tr><th>Input</th><th>Result</th></tr></thead><tbody><tr><th>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span> <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"light"</span> <span class="hljs-punctuation">}</span>
</code></pre>
</th><td>

<ol>
<li><code>foundation/size.json</code></li>
<li><code>foundation/typography.json</code></li>
<li><code>foundation/animation.json</code></li>
<li><code>theme/light.json</code></li>
</ol>
</td></tr><tr><th>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span> <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"lightHighContrast"</span> <span class="hljs-punctuation">}</span>
</code></pre>
</th><td>

<ol>
<li><code>foundation/size.json</code></li>
<li><code>foundation/typography.json</code></li>
<li><code>foundation/animation.json</code></li>
<li><code>theme/light.json</code></li>
<li><code>theme/light-high-contrast.json</code></li>
</ol>
</td></tr><tr><th>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span> <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"dark"</span> <span class="hljs-punctuation">}</span>
</code></pre>
</th><td>

<ol>
<li><code>foundation/size.json</code></li>
<li><code>foundation/typography.json</code></li>
<li><code>foundation/animation.json</code></li>
<li><code>theme/dark.json</code></li>
</ol>
</td></tr><tr><th>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span> <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"darkHighContrast"</span> <span class="hljs-punctuation">}</span>
</code></pre>
</th><td>

<ol>
<li><code>foundation/size.json</code></li>
<li><code>foundation/typography.json</code></li>
<li><code>foundation/animation.json</code></li>
<li><code>theme/dark.json</code></li>
<li><code>theme/dark-high-contrast.json</code></li>
</ol>
</td></tr></tbody></table>

<p>In case of any conflict, the last occurrence of a design token produces the final value.</p>
</aside>

<aside class="example" id="example-empty-array-in-modifiers"><div class="marker">
    <a class="self-link" href="#example-empty-array-in-modifiers">Example<bdi> 7</bdi></a><span class="example-title">: Empty array in modifiers</span>
  </div>

<p>Modifiers <em class="rfc2119">MAY</em> contain empty context arrays:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"modifiers"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-comment">// …</span>
    <span class="hljs-attr">"debug"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"description"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Enable debug mode"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"contexts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"false"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"true"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"debug.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"resolutionOrder"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-comment">// …</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/modifiers/debug"</span> <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>This would then load an additional <code>debug.json</code> file if it received a <code>{ "debug": "true" }</code> <a href="#inputs">input</a>.</p>
</aside>

<section id="inline-sets-and-modifiers"><div class="header-wrapper"><h5 id="x4-1-6-1-inline-sets-and-modifiers"><bdi class="secno">4.1.6.1 </bdi>Inline sets and modifiers</h5><a class="self-link" href="#inline-sets-and-modifiers" aria-label="Permalink for Section 4.1.6.1"></a></div>
<p>In <code>resolutionOrder</code>, a <a href="#sets">set</a> or <a href="#modifiers">modifier</a> <em class="rfc2119">MAY</em> be declared inline, so long as <code>name</code> and <code>type</code> keys are added to the object:</p>
<table>
<thead>
<tr>
<th align="left">Property</th>
<th align="left">Type</th>
<th align="center">Required</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>name</strong></td>
<td align="left"><code>string</code></td>
<td align="center">Y</td>
<td align="left">A unique name that <em class="rfc2119">MUST NOT</em> conflict with any other <code>name</code> in <code>resolutionOrder</code>.</td>
</tr>
<tr>
<td align="left"><strong>type</strong></td>
<td align="left"><code>"set" | "modifier"</code></td>
<td align="center">Y</td>
<td align="left"><em class="rfc2119">MUST</em> be <code>"set"</code> or <code>"modifier"</code> according to the type.</td>
</tr>
</tbody></table>
<p>Tools <em class="rfc2119">MUST</em> throw an error in the case where <code>name</code> or <code>type</code> are missing from an inline object, or if <code>name</code> is duplicated among any objects.</p>
<div class="note" id="issue-container-generatedID"><div role="heading" class="ednote-title marker" id="h-ednote" aria-level="6"><span>Editor's note</span><span class="issue-label">: Name</span></div><aside class="">

<p>When sets and modifiers appear in their respective root level <code>sets</code> and <code>modifiers</code> keys, it is valid for a set to share a name with a modifier. It is only invalid to duplicate a <code>name</code> inside the <code>resolutionOrder</code> array.</p>
</aside></div>

<aside class="example" id="example-resolution-order-with-inline-sets-and-modifiers"><div class="marker">
    <a class="self-link" href="#example-resolution-order-with-inline-sets-and-modifiers">Example<bdi> 8</bdi></a><span class="example-title">: Resolution Order with inline sets and modifiers</span>
  </div>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"resolutionOrder"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"set"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Size"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"foundation/size.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"set"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Typography"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"foundation/typography.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"set"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Animation"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/Animation"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"modifier"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Theme"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"description"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Color theme"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"contexts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"light"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/light.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"lightHighContrast"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/light.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark-high-contrast.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"dark"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"darkHighContrast"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark-high-contrast.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"default"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"light"</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre>
</aside>

<p>Inline sets and modifiers <em class="rfc2119">MUST NOT</em> be referenced in any way. Tools <em class="rfc2119">SHOULD</em> throw an error when a <a href="#reference-objects">reference object</a> points to a resolution order item.</p>
<aside class="example" id="example-invalid-inline-set-reference"><div class="marker">
    <a class="self-link" href="#example-invalid-inline-set-reference">Example<bdi> 9</bdi></a><span class="example-title">: Invalid inline set reference</span>
  </div>

<p>The following <a href="#reference-objects">reference object</a> pointer is invalid regardless of where it appears:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/resolutionOrder/4"</span> <span class="hljs-punctuation">}</span>
</code></pre>
<p>This is very likely to create an invalid reference, no matter if it appears in <a href="#sets">sets</a> (circular dependency), <a href="#modifiers">modifiers</a> (circular dependency), or in another place in the <a href="#resolution-order">resolutionOrder</a> array (infinite recursion). The times where this would not cause an invalid reference are rare, and the slightest change may turn it into a circular reference.</p>
</aside>

</section><section class="informative" id="ordering-of-sets-and-modifiers"><div class="header-wrapper"><h5 id="x4-1-6-2-ordering-of-sets-and-modifiers"><bdi class="secno">4.1.6.2 </bdi>Ordering of sets and modifiers</h5><a class="self-link" href="#ordering-of-sets-and-modifiers" aria-label="Permalink for Section 4.1.6.2"></a></div><p><em>This section is non-normative.</em></p>


<p>The <code>resolutionOrder</code> array allows for any ordering of sets and modifiers to the user’s choosing. However, in the scenario that many sets must appear after the modifiers to resolve conflicts, it is likely a <a href="https://en.wikipedia.org/wiki/Code_smell">smell</a> of unpredictable and brittle token organization. Ideally, modifiers handle conditional values so well they require few or no overrides (see <a href="#orthogonality">orthogonality</a>). In practical terms, this means that</p>
</section>

</section></section><section id="reference-objects"><div class="header-wrapper"><h3 id="x4-2-reference-objects"><bdi class="secno">4.2 </bdi>Reference objects</h3><a class="self-link" href="#reference-objects" aria-label="Permalink for Section 4.2"></a></div>
<p>When referring to another JSON document or a structure within the same document, a reference object <em class="rfc2119">MUST</em> be used. This is described in <a href="https://json-schema.org/draft/2020-12/json-schema-core#ref">JSON Schema 2020-12</a> as an object with a key of <code>$ref</code> whose string is a valid JSON pointer as described in [<cite><a class="bibref" data-link-type="biblio" href="#bib-rfc6901" title="JavaScript Object Notation (JSON) Pointer">RFC6901</a></cite>].</p>
<p>Tools <em class="rfc2119">MUST</em> resolve all reference objects in a resolver document.</p>
<p>Reference objects <em class="rfc2119">MUST NOT</em> be circular, neither referencing other pointers that reference itself, nor referencing any parent node of the reference object.</p>
<p>Tools <em class="rfc2119">MUST</em> support same-document reference objects, as that is the minimum requirement to support this resolver module. Beyond that, tools may make individual decisions to not support some URI types such as importing files on a local file system, or remote URIs over TCP/IP.</p>
<aside class="example" id="example-valid-reference-objects"><div class="marker">
    <a class="self-link" href="#example-valid-reference-objects">Example<bdi> 10</bdi></a><span class="example-title">: Valid reference objects</span>
  </div>

<p>Common examples of reference objects include:</p>
<table><thead><tr><th>Code</th><th>Result</th><th>Required Support</th></tr></thead><tbody><tr><th>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/MySet"</span> <span class="hljs-punctuation">}</span>
</code></pre>
</th><td>

<p>References <code>sets/MySet</code> within the same document.</p>
</td><td>Y</td></tr><tr><th>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"path/to/example.json"</span> <span class="hljs-punctuation">}</span>
</code></pre>
</th><td>

<p>References the entire contents of <code>./path/to/example.json</code>, relative to this document.</p>
</td><td></td></tr><tr><th>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"example.json#sets/MySet"</span> <span class="hljs-punctuation">}</span>
</code></pre>
</th><td>

<p>References only a part of <code>example.json</code>: <code>sets/MySet</code>.</p>
</td><td></td></tr><tr><th>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://my-server.com/tokens.json"</span> <span class="hljs-punctuation">}</span>
</code></pre>
</th><td>

<p>References a remote file hosted at a publicly-available URL.</p>
</td><td></td></tr></tbody></table>

</aside>

<aside class="example" id="example-invalid-reference-objects"><div class="marker">
    <a class="self-link" href="#example-invalid-reference-objects">Example<bdi> 11</bdi></a><span class="example-title">: Invalid reference objects</span>
  </div>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"foo"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"bar"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/baz/bat"</span> <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"baz"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"bat"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/foo/bar"</span> <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>This example is invalid because both <code>foo/bar</code> and <code>baz/bat</code> reference one another and therefore have no final value.</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"foo"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"bar"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"baz"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/foo/bar"</span> <span class="hljs-punctuation">}</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>A single reference object that references its parent is invalid because it will include itself and infinitely recurse.</p>
</aside>

<section id="invalid-pointers"><div class="header-wrapper"><h4 id="x4-2-1-invalid-pointers"><bdi class="secno">4.2.1 </bdi>Invalid pointers</h4><a class="self-link" href="#invalid-pointers" aria-label="Permalink for Section 4.2.1"></a></div>
<p>A pointer <em class="rfc2119">MAY</em> point anywhere within the same document, with the exception of the following:</p>
<ol>
<li>Only <a href="#resolution-order">resolutionOrder</a> may reference a modifier (<code>#/modifiers/…</code>). Sets and modifiers <em class="rfc2119">MUST NOT</em> reference another modifier.<ul>
<li>Referencing a modifier from a set could cause <a href="#inputs">inputs</a> to apply conditional logic to a structure that can’t support it, therefore it’s not allowed.</li>
<li>Referencing a modifier from another modifier would mean a single input applies to unexpected modifiers, therefore it’s not allowed.</li>
</ul>
</li>
<li>A reference object <em class="rfc2119">MUST NOT</em> point to anything in the <a href="#resolution-order">resolutionOrder</a> array (<code>#/resolutionOrder/…</code>). Resolution ordering, by its nature, references many other parts of the document. Duplicating any part of this will produce complex, hard-to-predict chains.</li>
</ol>
<p>Tools <em class="rfc2119">MUST</em> throw an error if encountering any invalid pointers.</p>
</section><section id="extending"><div class="header-wrapper"><h4 id="x4-2-2-extending"><bdi class="secno">4.2.2 </bdi>Extending</h4><a class="self-link" href="#extending" aria-label="Permalink for Section 4.2.2"></a></div>
<p>As <a href="https://json-schema.org/draft/2020-12/json-schema-core#ref">JSON Schema 2020-12</a> allows, other keys <em class="rfc2119">MAY</em> exist on a reference object alongside <code>$ref</code>. In these scenarios, the local keys alongside <code>$ref</code> <em class="rfc2119">MUST</em> be treated as overrides.</p>
<aside class="example" id="example-extending-with-ref"><div class="marker">
    <a class="self-link" href="#example-extending-with-ref">Example<bdi> 12</bdi></a><span class="example-title">: Extending with $ref</span>
  </div>

<p>As a generic example:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"animal"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"color"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"brown"</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"legs"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">4</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"lizard"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"color"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"green"</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/animal"</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"size"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"small"</span>
  <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>The final value of <code>#/lizard</code> will be equivalent to:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"color"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"green"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"legs"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">4</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"size"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"small"</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>Key order does not matter. Since <code>color</code> is declared locally, it will replace the value in <code>#/animal</code>. Also adding the new property of <code>size</code> will append to the final value.</p>
</aside>

<p>If a key alongside <code>$ref</code> declares an object or array, tools <em class="rfc2119">MUST</em> flatten these shallowly, meaning objects and arrays are not merged.</p>
</section></section><section id="extensions"><div class="header-wrapper"><h3 id="x4-3-extensions"><bdi class="secno">4.3 </bdi>$extensions</h3><a class="self-link" href="#extensions" aria-label="Permalink for Section 4.3"></a></div>
<p>An <code>$extensions</code> object <em class="rfc2119">MAY</em> be added to any <a href="#sets">set</a>, <a href="#modifiers">modifier</a>, or <a href="#inline-sets-and-modifiers">inline set/modifier</a>, to declare arbitrary metadata that is up to individual tools to either use or ignore.</p>
<p>If provided, <code>$extensions</code> <em class="rfc2119">MUST</em> be an object with the keys being vendor-specific namespaces. This allows multiple tools to use this metadata without conflict.</p>
<aside class="example" id="example-set-with-extensions"><div class="marker">
    <a class="self-link" href="#example-set-with-extensions">Example<bdi> 13</bdi></a><span class="example-title">: Set with $extensions</span>
  </div>

<p>Here is an example where a set contains arbitrary metadata for the <code>figma.com</code> vendor:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"sets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"color"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
        <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"colors/ramps.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
        <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"colors/semantic.json"</span> <span class="hljs-punctuation">}</span>
      <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"$extensions"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"figma.com"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
          <span class="hljs-attr">"sourceFile"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://figma.com/file/xxxxxx"</span><span class="hljs-punctuation">,</span>
          <span class="hljs-attr">"updatedAt"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2025-11-01"</span>
        <span class="hljs-punctuation">}</span>
      <span class="hljs-punctuation">}</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">}</span>
</code></pre>
</aside>

</section><section id="defs"><div class="header-wrapper"><h3 id="x4-4-defs"><bdi class="secno">4.4 </bdi>$defs</h3><a class="self-link" href="#defs" aria-label="Permalink for Section 4.4"></a></div>
<p>Tools <em class="rfc2119">MAY</em> allow defining structures in JSON Schema <a href="https://json-schema.org/understanding-json-schema/structuring#defs">$defs</a> but is not a requirement. However, tools <em class="rfc2119">MUST NOT</em> throw an error when encountering <code>$defs</code>, and <em class="rfc2119">MUST</em> ignore the key if it is not supported.</p>
<div class="note" id="issue-container-generatedID-0"><div role="heading" class="ednote-title marker" id="h-ednote-0" aria-level="4"><span>Editor's note</span><span class="issue-label">: $defs</span></div><aside class="">

<p>Using <code>$defs</code> is undefined behavior as far as this specification is concerned, so it is up to users and toolmakers to either define a usage or avoid entirely. The specification intentionally avoids using <code>$defs</code> so there will be no chance of future conflict.</p>
</aside></div></section></section>

    <section id="inputs"><div class="header-wrapper"><h2 id="x5-inputs"><bdi class="secno">5. </bdi>Inputs</h2><a class="self-link" href="#inputs" aria-label="Permalink for Section 5."></a></div>
<p>A resolver document only describes how conditional token values <em class="rfc2119">MAY</em> be produced. But the conditions must still be provided somewhere. The term “input” refers to any selection of context values passed to the tool.</p>
<p>Tools <em class="rfc2119">MUST</em> accept inputs as a JSON-serializable object, such as an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">object in JavaScript</a> or a <a href="https://docs.python.org/3/tutorial/datastructures.html#dictionaries">dictionary in Python</a>.</p>
<p>Tools that load a resolver that declares modifiers <em class="rfc2119">SHOULD</em> throw an error if an accompanying input is not provided.</p>
<aside class="example" id="example-inputs"><div class="marker">
    <a class="self-link" href="#example-inputs">Example<bdi> 14</bdi></a><span class="example-title">: Inputs</span>
  </div>

<p>Given the following modifiers:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"resolutionOrder"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"modifier"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"contexts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"light"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"light.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"dark"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"dark.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"modifier"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"size"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"context"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"default"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"size/default.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"large"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"size/large.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"modifier"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"beta"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"context"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"false"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"true"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"beta.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"default"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"false"</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>A <strong>valid</strong> input would follow the schema: all keys correspond to the <code>name</code> of each modifier. The values are valid options as designated by the modifier.</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"light"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"size"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"large"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"beta"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"true"</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>However, an <strong>invalid</strong> input would add unknown keys, invalid contexts, and/or missing required modifiers:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"blue"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"foo"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"bar"</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>In this scenario, tools <em class="rfc2119">SHOULD</em> throw multiple errors along the lines of:</p>
<ol>
<li><code>Error: invalid context "blue" for modifier "theme".</code></li>
<li><code>Error: missing modifier "size".</code></li>
<li><code>Error: unknown modifier "foo".</code></li>
<li>(no error needed for modifier <code>beta</code>, as it provided a <code>default</code>)</li>
</ol>
</aside>

<aside class="example" id="example-tool-consuming-input"><div class="marker">
    <a class="self-link" href="#example-tool-consuming-input">Example<bdi> 15</bdi></a><span class="example-title">: Tool consuming input</span>
  </div>

<p>Using an imaginary tool written in JavaScript, we could potentially consume <a href="#example-inputs">the previous example</a> like so:</p>
<pre><code class="js hljs" aria-busy="false"><span class="hljs-keyword">import</span> tokenTool <span class="hljs-keyword">from</span> <span class="hljs-string">'./token-tool.js'</span>;

tokenTool.<span class="hljs-title function_">loadResolver</span>(
  <span class="hljs-comment">/* Path to resolver */</span>
  <span class="hljs-string">'./resolver.json'</span>,

  <span class="hljs-comment">/* Input */</span>
  {
    <span class="hljs-attr">theme</span>: <span class="hljs-string">'dark'</span>,
    <span class="hljs-attr">size</span>: <span class="hljs-string">'default'</span>,
  },
);
</code></pre>
<p>This imaginary tool has a <code>loadResolver()</code> method that takes as its parameters:</p>
<ol>
<li>A filepath to the resolver in the first position, and</li>
<li>The input object in its 2nd position.</li>
</ol>
<p>The tool then combines the resolver + inputs to produce its final <a data-link-type="dfn" href="https://www.w3.org/policies/process/#group-decision">resolution</a>.</p>
</aside>

<section id="case-sensitivity"><div class="header-wrapper"><h3 id="x5-1-case-sensitivity"><bdi class="secno">5.1 </bdi>Case sensitivity</h3><a class="self-link" href="#case-sensitivity" aria-label="Permalink for Section 5.1"></a></div>
<p>Inputs <em class="rfc2119">SHOULD</em> be case-insensitive. For example, <code>{ "theme": "dark" }</code>, <code>{ "Theme": "Dark" }</code>, and <code>{ "THEME": "DARK" }</code> <em class="rfc2119">SHOULD</em> be equivalent. However, tools <em class="rfc2119">MAY</em> make individual decisions on case sensitivity.</p>
</section><section id="enforcing-strings"><div class="header-wrapper"><h3 id="x5-2-enforcing-strings"><bdi class="secno">5.2 </bdi>Enforcing strings</h3><a class="self-link" href="#enforcing-strings" aria-label="Permalink for Section 5.2"></a></div>
<p>Inputs <em class="rfc2119">MUST</em> have strings as their values. Tools <em class="rfc2119">MUST</em> throw an error if an input contains a non-string value, such as <code>{ "beta": true }</code> or <code>{ "size": 100 }</code>.</p>
</section></section>

    <section id="resolution-logic"><div class="header-wrapper"><h2 id="x6-resolution-logic"><bdi class="secno">6. </bdi>Resolution logic</h2><a class="self-link" href="#resolution-logic" aria-label="Permalink for Section 6."></a></div>
<p>Tools <em class="rfc2119">MUST</em> handle the resolution stages in order to produce the correct output.</p>
<ol>
<li><a href="#input-validation">Input validation</a>: verifying the <a href="#inputs">input</a> is valid for the given resolver document.</li>
<li><a href="#ordering">Ordering</a>: tracing the <code>resolutionOrder</code> array to produce the final tokens structure.</li>
<li><a href="#aliases">Aliases</a>: resolving token aliases in the final tokens structure.</li>
<li><a href="#resolution">Resolution</a>: the final end result</li>
</ol>
<section id="input-validation"><div class="header-wrapper"><h3 id="x6-1-input-validation"><bdi class="secno">6.1 </bdi>Input validation</h3><a class="self-link" href="#input-validation" aria-label="Permalink for Section 6.1"></a></div>
<p>Tools <em class="rfc2119">MUST</em> require all <a data-link-type="element" href="https://html.spec.whatwg.org/multipage/input.html#the-input-element">inputs</a> match the provided <a href="#modifiers">modifier</a> contexts.</p>
<p>If a resolver does NOT declare any modifiers, skip this step and proceed to <a href="#ordering">ordering</a>.</p>
<ol>
<li>For every key in the input object:<ol>
<li>Verify it corresponds with a valid modifier. If it does not, throw an error.</li>
<li>Verify that key’s value corresponds with that modifier’s allowed values. If it does not, throw an error.</li>
</ol>
</li>
<li>For every modifier in the resolver:<ol>
<li>If that resolver does NOT declare a default value, verify a key is provided in the input. If not, throw an error.</li>
</ol>
</li>
</ol>
</section><section id="ordering"><div class="header-wrapper"><h3 id="x6-2-ordering"><bdi class="secno">6.2 </bdi>Ordering</h3><a class="self-link" href="#ordering" aria-label="Permalink for Section 6.2"></a></div>
<p>Tools <em class="rfc2119">MUST</em> iterate over the <a href="#resolution-order">resolutionOrder</a> array in order.</p>
<ol>
<li><p>For every item in the array, determine whether it’s a <a href="#sets">set</a> or <a href="#modifiers">modifier</a>, flattening into a single tokens structure in array order.</p>
<ol>
<li>If the item is a set, combine the <code>sources</code> in array order to produce a single tokens structure.</li>
<li>Otherwise, if the item is a modifier, select only the <code>context</code> that matches the <a href="#inputs">input</a>, combining the array in order to produce a single tokens structure.</li>
<li>In case of a conflict, take the most recent occurrence in the array.</li>
</ol>
</li>
<li><p>Repeat until you’ve reached the end of the <code>resolutionOrder</code> array.</p>
</li>
</ol>
<p>The final result will be a tokens structure that behaves the same as if it were one source to begin with.</p>
<aside class="example" id="example-conflict-resolution"><div class="marker">
    <a class="self-link" href="#example-conflict-resolution">Example<bdi> 16</bdi></a><span class="example-title">: Conflict resolution</span>
  </div>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"sets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"foundation"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
        <span class="hljs-punctuation">{</span>
          <span class="hljs-attr">"color"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
            <span class="hljs-attr">"text"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
              <span class="hljs-attr">"default"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
                <span class="hljs-attr">"$value"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"colorSpace"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"srgb"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"components"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-number">0</span><span class="hljs-punctuation">,</span> <span class="hljs-number">0</span><span class="hljs-punctuation">,</span> <span class="hljs-number">0</span><span class="hljs-punctuation">]</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
                <span class="hljs-attr">"$type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"color"</span>
              <span class="hljs-punctuation">}</span>
            <span class="hljs-punctuation">}</span>
          <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
        <span class="hljs-punctuation">{</span>
          <span class="hljs-attr">"color"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
            <span class="hljs-attr">"text"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
              <span class="hljs-attr">"default"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
                <span class="hljs-attr">"$value"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
                  <span class="hljs-attr">"colorSpace"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"srgb"</span><span class="hljs-punctuation">,</span>
                  <span class="hljs-attr">"components"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-number">0.1</span><span class="hljs-punctuation">,</span> <span class="hljs-number">0.1</span><span class="hljs-punctuation">,</span> <span class="hljs-number">0.1</span><span class="hljs-punctuation">]</span>
                <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
                <span class="hljs-attr">"$type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"color"</span>
              <span class="hljs-punctuation">}</span>
            <span class="hljs-punctuation">}</span>
          <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">}</span>
      <span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"resolutionOrder"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/foundation"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>Here, two <code>color.text.default</code> tokens were encountered. Since order matters, the last declaration “wins” and the final result will be:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"color"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"text"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"default"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"$value"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"colorSpace"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"srgb"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"components"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-number">0.1</span><span class="hljs-punctuation">,</span> <span class="hljs-number">0.1</span><span class="hljs-punctuation">,</span> <span class="hljs-number">0.1</span><span class="hljs-punctuation">]</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"$type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"color"</span>
      <span class="hljs-punctuation">}</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">}</span>
</code></pre>
</aside>

</section><section id="aliases"><div class="header-wrapper"><h3 id="x6-3-aliases"><bdi class="secno">6.3 </bdi>Aliases</h3><a class="self-link" href="#aliases" aria-label="Permalink for Section 6.3"></a></div>
<p>Aliases <em class="rfc2119">MUST NOT</em> be resolved until this step.</p>
<p>After the <a href="#ordering">ordering</a> has been flattened into a single tokens structure, the only remaining step is resolving aliases. Aliases are resolved the exact same way as outlined in the <a href="../format/#aliases-references">format</a>:</p>
<ul>
<li>Deep aliases are allowed, so long as they’re not circular</li>
<li>An alias must point to the correct <code>$type</code>.</li>
</ul>
</section><section id="resolution"><div class="header-wrapper"><h3 id="x6-4-resolution"><bdi class="secno">6.4 </bdi>Resolution</h3><a class="self-link" href="#resolution" aria-label="Permalink for Section 6.4"></a></div>
<aside class="example" id="example-theme-resolution"><div class="marker">
    <a class="self-link" href="#example-theme-resolution">Example<bdi> 17</bdi></a><span class="example-title">: Theme resolution</span>
  </div>

<p>We’ll start with the following file structure, followed by walking through the resolution stages step-by-step.</p>
<table>
<thead><tr><th>Name</th><th>Contents</th></tr></thead>

<tbody><tr><th>

<p>Resolver</p>
</th><td>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"sets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"foundation"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"foundation.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"components"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"components/button.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"modifiers"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"context"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"light"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"themes/light.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"dark"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"themes/dark.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"resolutionOrder"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/foundation"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/components"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/modifiers/theme"</span> <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre>
</td></tr><tr><th>

<p>Input</p>
</th><td>

<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span> <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"dark"</span> <span class="hljs-punctuation">}</span>
</code></pre>
</td></tr><tr><th>

<p>foundation.json</p>
</th><td>

<ul>
<li><code>color.brand.primary</code> (color)</li>
</ul>
</td></tr><tr><th>

<p>components/button.json</p>
</th><td>

<ul>
<li><code>button.background</code> (color)</li>
<li><code>button.padding</code> (dimension)</li>
</ul>
</td></tr><tr><th>

<p>themes/light.json</p>
</th><td>

<ul>
<li><code>theme.accent</code></li>
</ul>
</td></tr><tr><th>

<p>themes/dark.json</p>
</th><td>

<ul>
<li><code>theme.accent</code> (alternate value)</li>
</ul>
</td></tr></tbody></table>

<ol>
<li>Input Validation<ol>
<li>Verify that <code>theme</code> is a defined modifier (it passes).</li>
<li>Verify that <code>dark</code> is a valid value for the <code>theme</code> modifier (it passes).</li>
</ol>
</li>
<li>Ordering<ol>
<li>The first item is the <code>foundation</code> set, providing <code>color.brand.primary</code>.</li>
<li>The second item is the <code>components</code> set, providing <code>button.background</code> and <code>button.padding</code>.</li>
<li>The third and final item is the <code>theme</code> modifier, providing <code>theme.accent</code>.</li>
<li>Thus, the final resolution includes 4 tokens.</li>
</ol>
</li>
<li>Alias<ol>
<li>If any tokens contain aliases, only at this point may they be resolved</li>
</ol>
</li>
<li>Resolution<ol>
<li>The final tokens spread looks like:<ol>
<li><code>color.brand.primary</code> (from <code>foundation.json</code>)</li>
<li><code>button.background</code> (from <code>components/button.json</code>)</li>
<li><code>button.padding</code> (from <code>components/button.json</code>)</li>
<li><code>theme.accent</code> (from <code>themes/dark.json</code>)</li>
</ol>
</li>
</ol>
</li>
</ol>
<p>Key takeaways:</p>
<ul>
<li><code>themes/light.json</code> was never used since the input was <code>{ "theme": "dark" }</code>.</li>
</ul>
</aside></section></section>

    <section class="informative" id="bundling"><div class="header-wrapper"><h2 id="x7-bundling"><bdi class="secno">7. </bdi>Bundling</h2><a class="self-link" href="#bundling" aria-label="Permalink for Section 7."></a></div><p><em>This section is non-normative.</em></p>
<p>A resolver document allows for the use of tokens to exist in multiple JSON files for organization. But for the purposes of portability, it may be advantageous to deal with only a single JSON document.</p>
<p>“Bundling” refers to the process by which a resolver document may be reduced down into a single file. There are multiple strategies to accomplish this, more than this document outlines. But for the purpose of illustration, this will outline 2 of the many possible approaches:</p>
<section id="inlining-files"><div class="header-wrapper"><h3 id="x7-1-inlining-files"><bdi class="secno">7.1 </bdi>Inlining files</h3><a class="self-link" href="#inlining-files" aria-label="Permalink for Section 7.1"></a></div>
<p>Inlining involves taking all <a href="#reference-objects">reference objects</a> to remote files, and replacing them with their contents. This is a simple strategy that accomplishes the end goal, but results in duplication whenever the same file is referenced multiple times. While a tool may not have any difficulty with duplicated tokens, a human reading this document may likely struggle reading the number of lines of code this would produce.</p>
<aside class="example" id="example-bundling-by-inlining"><div class="marker">
    <a class="self-link" href="#example-bundling-by-inlining">Example<bdi> 18</bdi></a><span class="example-title">: Bundling by inlining</span>
  </div>

<p>Given a resolver that references 5 files:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"sets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"foundation"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
        <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"foundation/colors.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
        <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"foundation/size.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
        <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"foundation/typography.json"</span> <span class="hljs-punctuation">}</span>
      <span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"modifiers"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"contexts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"light"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"foundation/colors.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/light.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"dark"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"foundation/colors.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"theme/dark.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"resolutionOrder"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/foundation"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/modifiers/theme"</span> <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>One could inline the contents, resulting in:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"sets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"foundation"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
        <span class="hljs-punctuation">{</span>
          <span class="hljs-comment">// (contents of foundation/colors.json)</span>
        <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
        <span class="hljs-punctuation">{</span>
          <span class="hljs-comment">// (contents of foundation/size.json)</span>
        <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
        <span class="hljs-punctuation">{</span>
          <span class="hljs-comment">// (contents of foundation/typography.json)</span>
        <span class="hljs-punctuation">}</span>
      <span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"modifiers"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"contexts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"light"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span>
            <span class="hljs-comment">// (contents of foundation/colors.json)</span>
          <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span>
            <span class="hljs-comment">// (contents of theme/light.json)</span>
          <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"dark"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span>
            <span class="hljs-comment">// (contents of foundation/colors.json)</span>
          <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span>
            <span class="hljs-comment">// (contents of theme/dark.json)</span>
          <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"resolutionOrder"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/foundation"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/modifiers/theme"</span> <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>The contents of the files were abbreviated for readability. Their contents could be anything and aren’t relevant to the topic of bundling.</p>
<p>Note that <code>foundation/colors.json</code> was referenced 3 times in the document, so inlining produced 3 copies of the same contents.</p>
</aside>

</section><section id="using-defs-for-files"><div class="header-wrapper"><h3 id="x7-2-using-defs-for-files"><bdi class="secno">7.2 </bdi>Using $defs for files</h3><a class="self-link" href="#using-defs-for-files" aria-label="Permalink for Section 7.2"></a></div>
<p>As described in <a href="#defs">$defs</a>, <code>$defs</code> don’t have defined behavior in a resolver document. They may only be used if a tool decides to support this feature of JSON Schema.</p>
<p>This strategy involves creating a top-level <code>$defs</code> key, with each top-level key containing the contents for that file.</p>
<p>The only downside of using <code>$defs</code> is some tools may choose to ignore it, as it is not a minimum requirement of a resolver document.</p>
<aside class="example" id="example-bundling-by-using-defs"><div class="marker">
    <a class="self-link" href="#example-bundling-by-using-defs">Example<bdi> 19</bdi></a><span class="example-title">: Bundling by using $defs</span>
  </div>

<p>Given the same resolver <a href="#inlining-files">from the inlining section</a>, we can create a new top-level <code>$defs</code> key, and adding keys and values that correspond to filenames and its contents, respectively:</p>
<pre><code class="json hljs" aria-busy="false"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"sets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"foundation"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
        <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/$defs/foundation~1colors.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
        <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/$defs/foundation~1size.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
        <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/$defs/foundation~1typography.json"</span> <span class="hljs-punctuation">}</span>
      <span class="hljs-punctuation">]</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"modifiers"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"theme"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"contexts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"light"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/$defs/foundation~1colors.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/$defs/theme~1light.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
        <span class="hljs-attr">"dark"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/$defs/foundation~1colors.json"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
          <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/$defs/theme~1dark.json"</span> <span class="hljs-punctuation">}</span>
        <span class="hljs-punctuation">]</span>
      <span class="hljs-punctuation">}</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"resolutionOrder"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/sets/foundation"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"$ref"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"#/modifiers/theme"</span> <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"$defs"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"foundation/colors.json"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-comment">// (contents of foundation/colors.json)</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"foundation/size.json"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-comment">// (contents of foundation/size.json)</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"foundation/typography.json"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-comment">// (contents of foundation/typography.json)</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"theme/light.json"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-comment">// (contents of theme/light.json)</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"theme/dark.json"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
      <span class="hljs-comment">// (contents of theme/dark.json)</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<p>Using this method, we’ve not only reduced the deduplication, but we’ve also preserved the format and shape of the original resolver document without adding any length.</p>
<p>It’s worth noting that when the “<code>/</code>” character is used in a name, it must be escaped with <code>~1</code> according to [<cite><a class="bibref" data-link-type="biblio" href="#bib-rfc6901" title="JavaScript Object Notation (JSON) Pointer">RFC6901</a></cite>] so it’s not treated as a subpath. It’s also worth noting that because the filename appears after the <code>#</code> fragment character, “<code>[filename].json</code>” is referring to a point in the same document and not an actual file (otherwise it would appear before “<code>#</code>”).</p>
</aside></section></section>

    <section id="conformance"><div class="header-wrapper"><h2 id="x8-conformance"><bdi class="secno">8. </bdi>Conformance</h2><a class="self-link" href="#conformance" aria-label="Permalink for Section 8."></a></div><p>As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.</p><p>
        The key words <em class="rfc2119">MAY</em>, <em class="rfc2119">MUST</em>, <em class="rfc2119">MUST NOT</em>, <em class="rfc2119">SHOULD</em>, and <em class="rfc2119">SHOULD NOT</em> in this document
        are to be interpreted as described in
        <a href="https://www.rfc-editor.org/info/bcp14">BCP 14</a>
        [<cite><a class="bibref" data-link-type="biblio" href="#bib-rfc2119" title="Key words for use in RFCs to Indicate Requirement Levels">RFC2119</a></cite>] [<cite><a class="bibref" data-link-type="biblio" href="#bib-rfc8174" title="Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words">RFC8174</a></cite>]
        when, and only when, they appear in all
        capitals, as shown here.
      </p><p>Tools implementing the Resolver Specification <em class="rfc2119">MUST</em>:</p>
<ul>
<li><strong>Support the Resolution Process</strong>: Implement the <a href="#resolution-logic">resolution logic</a> as defined, including input validation, base set flattening, modifier application, aliasing, and conflict resolution.</li>
<li><strong>Validate Inputs</strong>: Ensure that provided modifier inputs match the defined modifiers and acceptable values.</li>
<li><strong>Resolve Aliases Correctly</strong>: Handle <a href="../format/#aliases-references">token references</a> accurately, including recursive references and detection of circular dependencies.</li>
<li><strong>Preserve Token Properties</strong>: Maintain additional token properties (e.g., <a href="#extensions">$extensions</a>) throughout the resolution process.</li>
<li><strong>Handle Errors Gracefully</strong>: Provide meaningful error messages for issues like invalid inputs or circular references.</li>
</ul>
</section>

    <section id="acknowledgements" class="appendix informative"><div class="header-wrapper"><h2 id="a-acknowledgments"><bdi class="secno">A. </bdi>Acknowledgments</h2><a class="self-link" href="#acknowledgements" aria-label="Permalink for Appendix A."></a></div><p><em>This section is non-normative.</em></p>
      
      <p>
        This resolver spec wouldn’t have happened without the Hyma Team,
        including but not limited to Mike Kamminga, Andrew L’Homme, and Lilith.
        Significant contributions were also made by Joren Broekema, Louis
        Chenais. We thank the members of the Design Tokens Community Group for
        their contributions and feedback.
      </p>
    </section>
  

<section id="references" class="appendix"><div class="header-wrapper"><h2 id="b-references"><bdi class="secno">B. </bdi>References</h2><a class="self-link" href="#references" aria-label="Permalink for Appendix B."></a></div><section id="normative-references"><div class="header-wrapper"><h3 id="b-1-normative-references"><bdi class="secno">B.1 </bdi>Normative references</h3><a class="self-link" href="#normative-references" aria-label="Permalink for Appendix B.1"></a></div>
    
    <dl class="bibliography"><dt id="bib-html">[html]</dt><dd>
      <a href="https://html.spec.whatwg.org/multipage/"><cite>HTML Standard</cite></a>. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters.  WHATWG. Living Standard. URL: <a href="https://html.spec.whatwg.org/multipage/">https://html.spec.whatwg.org/multipage/</a>
    </dd><dt id="bib-rfc1341">[RFC1341]</dt><dd>
      <a href="https://www.rfc-editor.org/rfc/rfc1341"><cite>MIME (Multipurpose Internet Mail Extensions): Mechanisms for Specifying and Describing the Format of Internet Message Bodies</cite></a>. N. Borenstein; N. Freed.  IETF. June 1992. Proposed Standard. URL: <a href="https://www.rfc-editor.org/rfc/rfc1341">https://www.rfc-editor.org/rfc/rfc1341</a>
    </dd><dt id="bib-rfc2119">[RFC2119]</dt><dd>
      <a href="https://www.rfc-editor.org/rfc/rfc2119"><cite>Key words for use in RFCs to Indicate Requirement Levels</cite></a>. S. Bradner.  IETF. March 1997. Best Current Practice. URL: <a href="https://www.rfc-editor.org/rfc/rfc2119">https://www.rfc-editor.org/rfc/rfc2119</a>
    </dd><dt id="bib-rfc6838">[RFC6838]</dt><dd>
      <a href="https://www.rfc-editor.org/rfc/rfc6838"><cite>Media Type Specifications and Registration Procedures</cite></a>. N. Freed; J. Klensin; T. Hansen.  IETF. January 2013. Best Current Practice. URL: <a href="https://www.rfc-editor.org/rfc/rfc6838">https://www.rfc-editor.org/rfc/rfc6838</a>
    </dd><dt id="bib-rfc6901">[RFC6901]</dt><dd>
      <a href="https://www.rfc-editor.org/rfc/rfc6901"><cite>JavaScript Object Notation (JSON) Pointer</cite></a>. P. Bryan, Ed.; K. Zyp; M. Nottingham, Ed. IETF. April 2013. Proposed Standard. URL: <a href="https://www.rfc-editor.org/rfc/rfc6901">https://www.rfc-editor.org/rfc/rfc6901</a>
    </dd><dt id="bib-rfc8174">[RFC8174]</dt><dd>
      <a href="https://www.rfc-editor.org/rfc/rfc8174"><cite>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</cite></a>. B. Leiba.  IETF. May 2017. Best Current Practice. URL: <a href="https://www.rfc-editor.org/rfc/rfc8174">https://www.rfc-editor.org/rfc/rfc8174</a>
    </dd><dt id="bib-rfc8259">[RFC8259]</dt><dd>
      <a href="https://www.rfc-editor.org/rfc/rfc8259"><cite>The JavaScript Object Notation (JSON) Data Interchange Format</cite></a>. T. Bray, Ed. IETF. December 2017. Internet Standard. URL: <a href="https://www.rfc-editor.org/rfc/rfc8259">https://www.rfc-editor.org/rfc/rfc8259</a>
    </dd><dt id="bib-w3c-process">[w3c-process]</dt><dd>
      <a href="https://www.w3.org/policies/process/"><cite>W3C Process Document</cite></a>. Elika J. Etemad (fantasai); Florian Rivoal.  W3C. 18 August 2025. URL: <a href="https://www.w3.org/policies/process/">https://www.w3.org/policies/process/</a>
    </dd></dl>
  </section></section><p role="navigation" id="back-to-top">
    <a href="#title"><abbr title="Back to Top">↑</abbr></a>
  </p><script id="respec-highlight-vars">(() => {
// @ts-check

if (document.respec) {
  document.respec.ready.then(setupVarHighlighter);
} else {
  setupVarHighlighter();
}

function setupVarHighlighter() {
  document
    .querySelectorAll("var")
    .forEach(varElem => varElem.addEventListener("click", highlightListener));
}

function highlightListener(ev) {
  ev.stopPropagation();
  const { target: varElem } = ev;
  const hightligtedElems = highlightVars(varElem);
  const resetListener = () => {
    const hlColor = getHighlightColor(varElem);
    hightligtedElems.forEach(el => removeHighlight(el, hlColor));
    [...HL_COLORS.keys()].forEach(key => HL_COLORS.set(key, true));
  };
  if (hightligtedElems.length) {
    document.body.addEventListener("click", resetListener, { once: true });
  }
}

// availability of highlight colors. colors from var.css
const HL_COLORS = new Map([
  ["respec-hl-c1", true],
  ["respec-hl-c2", true],
  ["respec-hl-c3", true],
  ["respec-hl-c4", true],
  ["respec-hl-c5", true],
  ["respec-hl-c6", true],
  ["respec-hl-c7", true],
]);

function getHighlightColor(target) {
  // return current colors if applicable
  const { value } = target.classList;
  const re = /respec-hl-\w+/;
  const activeClass = re.test(value) && value.match(re);
  if (activeClass) return activeClass[0];

  // first color preference
  if (HL_COLORS.get("respec-hl-c1") === true) return "respec-hl-c1";

  // otherwise get some other available color
  return [...HL_COLORS.keys()].find(c => HL_COLORS.get(c)) || "respec-hl-c1";
}

function highlightVars(varElem) {
  const textContent = norm(varElem.textContent);
  const parent = varElem.closest(".algorithm, section");
  const highlightColor = getHighlightColor(varElem);

  const varsToHighlight = [...parent.querySelectorAll("var")].filter(
    el =>
      norm(el.textContent) === textContent &&
      el.closest(".algorithm, section") === parent
  );

  // update availability of highlight color
  const colorStatus = varsToHighlight[0].classList.contains("respec-hl");
  HL_COLORS.set(highlightColor, colorStatus);

  // highlight vars
  if (colorStatus) {
    varsToHighlight.forEach(el => removeHighlight(el, highlightColor));
    return [];
  } else {
    varsToHighlight.forEach(el => addHighlight(el, highlightColor));
  }
  return varsToHighlight;
}

function removeHighlight(el, highlightColor) {
  el.classList.remove("respec-hl", highlightColor);
  // clean up empty class attributes so they don't come in export
  if (!el.classList.length) el.removeAttribute("class");
}

function addHighlight(elem, highlightColor) {
  elem.classList.add("respec-hl", highlightColor);
}

/**
 * Same as `norm` from src/core/utils, but our build process doesn't allow
 * imports in runtime scripts, so duplicated here.
 * @param {string} str
 */
function norm(str) {
  return str.trim().replace(/\s+/g, " ");
}
})()</script><script id="respec-dfn-panel">(() => {
// @ts-check
if (document.respec) {
  document.respec.ready.then(setupPanel);
} else {
  setupPanel();
}

function setupPanel() {
  const listener = panelListener();
  document.body.addEventListener("keydown", listener);
  document.body.addEventListener("click", listener);
}

function panelListener() {
  /** @type {HTMLElement} */
  let panel = null;
  return event => {
    const { target, type } = event;

    if (!(target instanceof HTMLElement)) return;

    // For keys, we only care about Enter key to activate the panel
    // otherwise it's activated via a click.
    if (type === "keydown" && event.key !== "Enter") return;

    const action = deriveAction(event);

    switch (action) {
      case "show": {
        hidePanel(panel);
        /** @type {HTMLElement} */
        const dfn = target.closest("dfn, .index-term");
        panel = document.getElementById(`dfn-panel-for-${dfn.id}`);
        const coords = deriveCoordinates(event);
        displayPanel(dfn, panel, coords);
        break;
      }
      case "dock": {
        panel.style.left = null;
        panel.style.top = null;
        panel.classList.add("docked");
        break;
      }
      case "hide": {
        hidePanel(panel);
        panel = null;
        break;
      }
    }
  };
}

/**
 * @param {MouseEvent|KeyboardEvent} event
 */
function deriveCoordinates(event) {
  const target = /** @type HTMLElement */ (event.target);

  // We prevent synthetic AT clicks from putting
  // the dialog in a weird place. The AT events sometimes
  // lack coordinates, so they have clientX/Y = 0
  const rect = target.getBoundingClientRect();
  if (
    event instanceof MouseEvent &&
    event.clientX >= rect.left &&
    event.clientY >= rect.top
  ) {
    // The event probably happened inside the bounding rect...
    return { x: event.clientX, y: event.clientY };
  }

  // Offset to the middle of the element
  const x = rect.x + rect.width / 2;
  // Placed at the bottom of the element
  const y = rect.y + rect.height;
  return { x, y };
}

/**
 * @param {Event} event
 */
function deriveAction(event) {
  const target = /** @type {HTMLElement} */ (event.target);
  const hitALink = !!target.closest("a");
  if (target.closest("dfn:not([data-cite]), .index-term")) {
    return hitALink ? "none" : "show";
  }
  if (target.closest(".dfn-panel")) {
    if (hitALink) {
      return target.classList.contains("self-link") ? "hide" : "dock";
    }
    const panel = target.closest(".dfn-panel");
    return panel.classList.contains("docked") ? "hide" : "none";
  }
  if (document.querySelector(".dfn-panel:not([hidden])")) {
    return "hide";
  }
  return "none";
}

/**
 * @param {HTMLElement} dfn
 * @param {HTMLElement} panel
 * @param {{ x: number, y: number }} clickPosition
 */
function displayPanel(dfn, panel, { x, y }) {
  panel.hidden = false;
  // distance (px) between edge of panel and the pointing triangle (caret)
  const MARGIN = 20;

  const dfnRects = dfn.getClientRects();
  // Find the `top` offset when the `dfn` can be spread across multiple lines
  let closestTop = 0;
  let minDiff = Infinity;
  for (const rect of dfnRects) {
    const { top, bottom } = rect;
    const diffFromClickY = Math.abs((top + bottom) / 2 - y);
    if (diffFromClickY < minDiff) {
      minDiff = diffFromClickY;
      closestTop = top;
    }
  }

  const top = window.scrollY + closestTop + dfnRects[0].height;
  const left = x - MARGIN;
  panel.style.left = `${left}px`;
  panel.style.top = `${top}px`;

  // Find if the panel is flowing out of the window
  const panelRect = panel.getBoundingClientRect();
  const SCREEN_WIDTH = Math.min(window.innerWidth, window.screen.width);
  if (panelRect.right > SCREEN_WIDTH) {
    const newLeft = Math.max(MARGIN, x + MARGIN - panelRect.width);
    const newCaretOffset = left - newLeft;
    panel.style.left = `${newLeft}px`;
    /** @type {HTMLElement} */
    const caret = panel.querySelector(".caret");
    caret.style.left = `${newCaretOffset}px`;
  }

  // As it's a dialog, we trap focus.
  // TODO: when <dialog> becomes a implemented, we should really
  // use that.
  trapFocus(panel, dfn);
}

/**
 * @param {HTMLElement} panel
 * @param {HTMLElement} dfn
 * @returns
 */
function trapFocus(panel, dfn) {
  /** @type NodeListOf<HTMLAnchorElement> elements */
  const anchors = panel.querySelectorAll("a[href]");
  // No need to trap focus
  if (!anchors.length) return;

  // Move focus to first anchor element
  const first = anchors.item(0);
  first.focus();

  const trapListener = createTrapListener(anchors, panel, dfn);
  panel.addEventListener("keydown", trapListener);

  // Hiding the panel releases the trap
  const mo = new MutationObserver(records => {
    const [record] = records;
    const target = /** @type HTMLElement */ (record.target);
    if (target.hidden) {
      panel.removeEventListener("keydown", trapListener);
      mo.disconnect();
    }
  });
  mo.observe(panel, { attributes: true, attributeFilter: ["hidden"] });
}

/**
 *
 * @param {NodeListOf<HTMLAnchorElement>} anchors
 * @param {HTMLElement} panel
 * @param {HTMLElement} dfn
 * @returns
 */
function createTrapListener(anchors, panel, dfn) {
  const lastIndex = anchors.length - 1;
  let currentIndex = 0;
  return event => {
    switch (event.key) {
      // Hitting "Tab" traps us in a nice loop around elements.
      case "Tab": {
        event.preventDefault();
        currentIndex += event.shiftKey ? -1 : +1;
        if (currentIndex < 0) {
          currentIndex = lastIndex;
        } else if (currentIndex > lastIndex) {
          currentIndex = 0;
        }
        anchors.item(currentIndex).focus();
        break;
      }

      // Hitting "Enter" on an anchor releases the trap.
      case "Enter":
        hidePanel(panel);
        break;

      // Hitting "Escape" returns focus to dfn.
      case "Escape":
        hidePanel(panel);
        dfn.focus();
        return;
    }
  };
}

/** @param {HTMLElement} panel */
function hidePanel(panel) {
  if (!panel) return;
  panel.hidden = true;
  panel.classList.remove("docked");
}
})()</script><script src="https://www.w3.org/scripts/TR/2021/fixup.js"></script></body></html>